package com.deeper.customview.ui.c7.demo.c07d04;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

public class MultiLauncher extends ViewGroup {

    private static final String TAG = "MultiLauncher";
    private static final int SNAP_VELOCITY = 600;
    private Scroller scroller;
    private int touchSlop = 0; //最小滑动距离
    private float lastMotionX = 0; //上次触摸屏的x位置

    private static final int TOUCH_STATE_STOP = 0x001;
    private static final int TOUCH_STATE_FLING = 0x002;
    private int touchState = TOUCH_STATE_STOP;


    public MultiLauncher(Context context) {
        super(context);
    }


    public MultiLauncher(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public MultiLauncher(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        scroller = new Scroller(context);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }


    private int measureWidth(int widthMeasureSpec) {
        int width = 0;
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            throw new IllegalStateException("must not be MeasureSpec.AT_MOST");
        } else {
            width = size;
        }
        //容器的宽度是屏幕的n倍，n是容器中子元素的个数
        return width * getChildCount();
    }


    private int measureHeight(int heightMeasureSpec) {
        int height = 0;
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            throw new IllegalStateException("must not be MeasureSpec.AT_MOST");
        } else {
            height = size;
        }
        return height;
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int n = getChildCount();
        int w = (r - l) / n;//分屏的宽度
        int h = b - t;//容器的高度

        for (int i = 0; i < n; i++) {
            View child = getChildAt(i);
            int left = i * w;
            int right = (i + 1) * w;
            int top = 0;
            int bottom = h;
            child.layout(left, top, right, bottom);
        }
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        final int x = (int) ev.getX();
        final int y = (int) ev.getY();
        if (action == MotionEvent.ACTION_MOVE &&
                touchState == TOUCH_STATE_STOP) {
            return true;
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                lastMotionX = x;
                touchState = scroller.isFinished() ? TOUCH_STATE_STOP
                        : TOUCH_STATE_FLING;
                break;
            case MotionEvent.ACTION_MOVE:
                //滑动距离过小不算滑动
                final int dx = (int) Math.abs(x - lastMotionX);
                if (dx > touchSlop) {
                    touchState = TOUCH_STATE_FLING;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                touchState = TOUCH_STATE_STOP;
                break;
            default:
                break;
        }
        return touchState != TOUCH_STATE_STOP;
    }


    private int curScreen; //当前屏
    private VelocityTracker velocityTracker;//速率跟踪器


    public void moveToScreen(int whichScreen) {
        Log.d(TAG, "moveToScreen: " + whichScreen);
        curScreen = whichScreen;
        if (curScreen > getChildCount() - 1) {
            curScreen = getChildCount() - 1;
        }
        if (curScreen < 0) {
            curScreen = 0;
        }

        int scrollX = getScrollX();
        //每一屏的宽度
        int splitWidth = getWidth() / getChildCount();
        //要移动的距离
        int dx = curScreen * splitWidth - scrollX;
        //开始移动
        scroller.startScroll(scrollX, 0, dx, 0, Math.abs(dx));
        invalidate();
    }


    public void moveToDestination() {
        //每一屏的宽度
        int splitWidth = getWidth() / getChildCount();
        //判断是回滚还是进入下一分屏
        int toScreen = (getScrollX() + splitWidth / 2) / splitWidth;
        //移动到目标分屏
        moveToScreen(toScreen);
    }


    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            //设置容器内组件的新位置
            this.scrollTo(scroller.getCurrX(), scroller.getCurrY());
            //重绘以刷新产生动画
            postInvalidate();
        }
    }


    /**
     * 滚动到下一屏
     */
    public void moveToNext() {
        moveToScreen(curScreen + 1);
    }


    /**
     * 滚动到上一屏
     */
    public void moveToPrevious() {
        moveToScreen(curScreen - 1);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain();
        }
        velocityTracker.addMovement(event);
        super.onTouchEvent(event);

        int action = event.getAction();
        final int x = (int) event.getX();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //手指按下时，如果正在滚动，则立刻停止
                if (scroller != null && !scroller.isFinished()) {
                    scroller.abortAnimation();
                }
                lastMotionX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                //随手指滚动
                int dx = (int) (lastMotionX - x);
                scrollBy(dx, 0);
                lastMotionX = x;
                break;
            case MotionEvent.ACTION_UP:
                final VelocityTracker velocityTracker = this.velocityTracker;
                velocityTracker.computeCurrentVelocity(1000);
                int velocityX = (int) velocityTracker.getXVelocity();
                //通过 velocityX 的正负值可以判断滑动方向
                if (velocityX > SNAP_VELOCITY && curScreen > 0) {
                    moveToPrevious();
                } else if (velocityX < -SNAP_VELOCITY && curScreen < (getChildCount() - 1)) {
                    moveToNext();
                } else {
                    moveToDestination();
                }

                if (velocityTracker != null) {
                    this.velocityTracker.clear();
                    this.velocityTracker.recycle();
                    this.velocityTracker = null;
                }
                touchState = TOUCH_STATE_STOP;
                break;
            case MotionEvent.ACTION_CANCEL:
                touchState = TOUCH_STATE_STOP;
                break;
        }
        return true;
    }
}
